﻿// CMyNew.cpp: 实现文件
//

#include "stdafx.h"
#include "Item.h"
#include "CMyNew.h"
#include "afxdialogex.h"
#include "CMyClasss.h"
#include <opencv2/opencv.hpp>
#include<Python.h>
#include<python.h>
#include<iostream>
#include<fstream>
#include<string>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wchar.h>
using namespace std;
using namespace cv;

// 二值化阈值
#define GRAY_THRESH 150


// 直线上点的个数
#define HOUGH_VOTE 50


// CMyNew 对话框

IMPLEMENT_DYNAMIC(CMyNew, CDialogEx)

CMyNew::CMyNew(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG1, pParent)
	, m_int(0)
	, m_int1(0)
	, car(_T(""))
{

}

CMyNew::~CMyNew()
{
}

void CMyNew::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_SLIDER1, m_Slider);
	DDX_Slider(pDX, IDC_SLIDER1, m_int);
	DDX_Control(pDX, IDC_SLIDER2, m_slider);
	DDX_Slider(pDX, IDC_SLIDER2, m_int1);
	//  DDX_Control(pDX, IDC_EDIT1, car);
	DDX_Text(pDX, IDC_EDIT1, car);
}


BEGIN_MESSAGE_MAP(CMyNew, CDialogEx)
	ON_BN_CLICKED(IDC_BUTTON1, &CMyNew::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON4, &CMyNew::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON7, &CMyNew::OnBnClickedButton7)
	ON_BN_CLICKED(IDC_BUTTON8, &CMyNew::OnBnClickedButton8)
	ON_BN_CLICKED(IDC_BUTTON11, &CMyNew::OnBnClickedButton11)
	ON_BN_CLICKED(IDC_BUTTON3, &CMyNew::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON5, &CMyNew::OnBnClickedButton5)
	ON_BN_CLICKED(IDC_BUTTON9, &CMyNew::OnBnClickedButton9)
	ON_BN_CLICKED(IDC_BUTTON10, &CMyNew::OnBnClickedButton10)
	ON_BN_CLICKED(IDC_BUTTON12, &CMyNew::OnBnClickedButton12)
	ON_BN_CLICKED(IDC_BUTTON13, &CMyNew::OnBnClickedButton13)
	ON_BN_CLICKED(IDC_CAR, &CMyNew::OnBnClickedCar)
	ON_WM_HSCROLL()
	ON_BN_CLICKED(IDC_BUTTON14, &CMyNew::OnBnClickedButton14)
END_MESSAGE_MAP()


// CMyNew 消息处理程序




BOOL CMyNew::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	namedWindow("view", WINDOW_AUTOSIZE);
	HWND hWnd = (HWND)cvGetWindowHandle("view");
	HWND hParent = ::GetParent(hWnd);
	::SetParent(hWnd, GetDlgItem(IDC_PIC_STATIC)->m_hWnd);
	::ShowWindow(hParent, SW_HIDE);
	namedWindow("view1", WINDOW_AUTOSIZE);
	HWND hWnd1 = (HWND)cvGetWindowHandle("view1");
	HWND hParent1 = ::GetParent(hWnd1);
	::SetParent(hWnd1, GetDlgItem(IDC_PIC_STATIC1)->m_hWnd);
	::ShowWindow(hParent1, SW_HIDE);
	namedWindow("view2", WINDOW_AUTOSIZE);
	HWND hWnd2 = (HWND)cvGetWindowHandle("view2");
	HWND hParent2 = ::GetParent(hWnd2);
	::SetParent(hWnd2, GetDlgItem(IDC_PIC_STATIC2)->m_hWnd);
	::ShowWindow(hParent2, SW_HIDE);

	m_Slider.SetRange(1, 100);//设置滑动范围为1到20
	m_Slider.SetPos(50);//设置滑块初始位置为1 
	m_slider.SetRange(0, 100);//设置滑动范围为1到20
	m_slider.SetPos(50);//设置滑块初始位置为1 
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

Mat image, image1, dstz;
double alpha, alpha1;

void CMyNew::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	CString picPath;   //定义图片路径变量  
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY |
		OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT, NULL, this);  //选择文件对话框  
	if (dlg.DoModal() == IDOK)
	{
		picPath = dlg.GetPathName();  //获取图片路径  
	}
	//CString to string  使用这个方法记得字符集选用“使用多字节字符”，不然会报错  
	string picpath = picPath.GetBuffer(0);
	ofstream f;
	f.open("D:/OpenCV/opencv_test/opencv_test/Python1/test01.txt", ios_base::out);
	if (!f.is_open())
	{
		system("pause");
	}
	f << picpath;
	f.close();
	image = imread(picpath);
	Mat imagedst;
	//以下操作获取图形控件尺寸并以此改变图片尺寸  
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&rect);
	Rect dst(rect.left, rect.top, rect.right, rect.bottom);
	resize(image, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view", imagedst);
}

void CMyNew::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	CString picPath;   //定义图片路径变量  
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY |
		OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT, NULL, this);  //选择文件对话框  
	if (dlg.DoModal() == IDOK)
	{
		picPath = dlg.GetPathName();  //获取图片路径  
	}
	//CString to string  使用这个方法记得字符集选用“使用多字节字符”，不然会报错  
	string picpath = picPath.GetBuffer(0);
	image1 = imread(picpath);
	Mat imagedst;
	//以下操作获取图形控件尺寸并以此改变图片尺寸  
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	Rect dst(rect.left, rect.top, rect.right, rect.bottom);
	resize(image1, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view1", imagedst);
}


void CMyNew::OnBnClickedButton7()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat img_canny(image.size(), CV_8UC1, Scalar(0));
	Canny(image, img_canny, 100, 300, 3, true);
	Mat imagedst;
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	resize(img_canny, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view1", imagedst);
}


void CMyNew::OnBnClickedButton8()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat out;
	GaussianBlur(image, out, Size(7, 7), 0, 0);
	Mat imagedst;
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	resize(out, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view1", imagedst);
}

Mat destImage(Mat image)
{
	Mat dest;
	dest = Mat::zeros(image.size(), image.type());
	int width = image.cols;
	int height = image.rows;
	int channels = image.channels();


	double alphe = 1.8; //(alphe > 1)
	int beta = -30;// 负数对比度越高
	Mat m1;
	image.convertTo(m1, CV_32F); //将原始图片数据（CV_8U类型）转换成CV_32类型，以提高操作的精度
	for (int row = 0; row < height; row++) {
		for (int col = 0; col < width; col++) {
			if (channels == 3) { //对于3通道
				float b = m1.at<Vec3f>(row, col)[0];
				float g = m1.at<Vec3f>(row, col)[1];
				float r = m1.at<Vec3f>(row, col)[2];


				dest.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(alphe * b + beta);
				dest.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(alphe * g + beta);
				dest.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(alphe * r + beta);
			}
			else if (channels == 1) { //对于单通道
				int pix = image.at<uchar>(row, col);
				dest.at<uchar>(row, col) = saturate_cast<uchar>(alphe * pix + beta);
			}
		}
	}
	return dest;
};

void CMyNew::OnBnClickedButton11()
{
	// TODO: 在此添加控件通知处理程序代码
	
	Mat dest = destImage(image);
	Mat imagedst;
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	resize(dest, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view1", imagedst);
}


bool try_use_gpu = false;
vector<Mat> imgs;

Mat stitchImage(Mat image, Mat image1)
{
	if (image.empty() || image1.empty())
	{
		cout << "Can't read image" << endl;
	}
	imgs.push_back(image);
	imgs.push_back(image1);
	Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
	// 使用stitch函数进行拼接
	Mat pano;
	Stitcher::Status status = stitcher.stitch(imgs, pano);
	return pano;
};

void CMyNew::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat pano = stitchImage(image, image1);
	// 
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC2)->GetClientRect(&rect);
	resize(pano, pano, cv::Size(rect.Width(), rect.Height()));
	imshow("view2", pano);
}


void CMyNew::OnBnClickedButton5()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat dstImage;
	blur(image, dstImage, Size(7, 7));
	Mat imagedst;
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	resize(dstImage, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view1", imagedst);
}

Mat addSaltNoise(Mat srcImage, int n)
{
	Mat resultImage = srcImage.clone();
	for (int k = 0; k < n; k++)
	{
		//随机取值行列
		int i = rand() % resultImage.cols;
		int j = rand() % resultImage.rows;
		//图像通道判定
		if (resultImage.channels() == 1)
			resultImage.at<uchar>(j, i) = 255;
		else
		{
			resultImage.at<Vec3b>(j, i)[0] = 255;
			resultImage.at<Vec3b>(j, i)[1] = 255;
			resultImage.at<Vec3b>(j, i)[2] = 255;
		}
	}
	return resultImage;
}

void CMyNew::OnBnClickedButton9()
{

	Mat resultImage = addSaltNoise(image, 500);

	Mat imagedst;
	//以下操作获取图形控件尺寸并以此改变图片尺寸  
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&rect);
	Rect dst(rect.left, rect.top, rect.right, rect.bottom);
	resize(resultImage, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view1", imagedst);
}

Mat addImage(Mat image, Mat image1, double alpha)
{
	double a = alpha / 100;
	Mat newImage;
	addWeighted(image, a, image1, 1 - a, 0.0, newImage);
	return newImage;
};

void CMyNew::OnBnClickedButton10()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat imagedst = addImage(image, image1, 50.0);
	//以下操作获取图形控件尺寸并以此改变图片尺寸  
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC2)->GetClientRect(&rect);
	Rect dst(rect.left, rect.top, rect.right, rect.bottom);
	resize(imagedst, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view2", imagedst);
	
}


void CMyNew::OnBnClickedButton12()
{
	Mat dts1;
	Mat imagedst;
	CRect rect;
	flip(image, dts1, 1);
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	Rect dst(rect.left, rect.top, rect.right, rect.bottom);
	resize(dts1, imagedst, cv::Size(rect.Width(), rect.Height()));


	imshow("view1", imagedst);

}


void CMyNew::OnBnClickedButton13()
{
	Mat dts1;
	Mat imagedst;
	CRect rect;
	flip(image, dts1, -1);
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	Rect dst(rect.left, rect.top, rect.right, rect.bottom);
	resize(dts1, imagedst, cv::Size(rect.Width(), rect.Height()));


	imshow("view1", imagedst);
}

void CMyNew::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CSliderCtrl* slider = (CSliderCtrl*)pScrollBar;
	CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
	if (slider == &m_Slider)
	{
		m_int = m_Slider.GetPos();
		Mat imagedst, imagedst1;
		//以下操作获取图形控件尺寸并以此改变图片尺寸 
		alpha = double(m_int) / 100;
		CRect rect;
		GetDlgItem(IDC_PIC_STATIC2)->GetClientRect(&rect);
		Rect dst(rect.left, rect.top, rect.right, rect.bottom);
		resize(image, imagedst, cv::Size(rect.Width(), rect.Height()));
		resize(image1, imagedst1, cv::Size(rect.Width(), rect.Height()));
		addWeighted(imagedst, alpha, imagedst1, 1 - alpha, 0.0, dstz);
		imshow("view2", dstz);
	}

	if (slider == &m_slider)
	{

		/*dstz1 = dstz.clone();
		m_int1 = m_slider.GetPos();
		val = m_int1;
		createTrackbar("变量值", "滑动条测试", &val, 100, back, 0);*/
		Mat dstz1, dstz2, dstz3;
		dstz1 = dstz.clone();
		dstz2 = dstz1;
		m_int1 = m_slider.GetPos();
		alpha1 = double(m_int1) / 50;
		addWeighted(dstz1, alpha, dstz2, 2 - alpha1, 0.0, dstz3);
		imshow("view2", dstz3);
	}
}


void CMyNew::OnBnClickedCar()
{
	// TODO: 在此添加控件通知处理程序代码
	Py_Initialize();//调用Py_Initialize()进行初始化
	PyObject * pModule = NULL;
	PyObject * pFunc = NULL;
	PyRun_SimpleString("import sys");
	PyRun_SimpleString("sys.path.append('D:/OpenCV/opencv_test/opencv_test/test01/x64/Debug')");
	pModule = PyImport_ImportModule("Python1");//调用的Python文件名
	pFunc = PyObject_GetAttrString(pModule, "hello");//调用的函数名
	//cout << &pFunc << endl;
	PyObject* pRet = PyEval_CallObject(pFunc, NULL);//调用函数,NULL表示参数为空
	//cout << pRet << endl;
	char *res;
	char *res1;
	wchar_t hz[256];
	PyArg_Parse(pRet, "s", &res);//转换返回类型
	//cout << "res:" << res<< endl;//输出结果
	int len = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)res, -1, NULL, 0);
	MultiByteToWideChar(CP_UTF8, 0, (LPCCH)res, -1, hz, len);
	setlocale(LC_ALL, "chs");
	//wprintf(L"%s", hz);
	//wcout << "res:" << hz << endl;//输出结果
	car = CString(hz);
	GetDlgItem(IDC_EDIT1)->SetWindowText(car);
	//MessageBox(car);
	Py_Initialize();//调用Py_Finalize,和Py_Initialize相对应的.
}

Mat imgCorrect(Mat image)
{
	Mat srcImg;
	cvtColor(image, srcImg, COLOR_RGB2GRAY);

	Point center(srcImg.cols / 2, srcImg.rows / 2);


	Mat padded;
	int opWidth = getOptimalDFTSize(srcImg.rows);
	int opHeight = getOptimalDFTSize(srcImg.cols);
	copyMakeBorder(srcImg, padded, 0, opWidth - srcImg.rows, 0, opHeight - srcImg.cols, BORDER_CONSTANT, Scalar::all(0));


	Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
	Mat comImg;

	merge(planes, 2, comImg);

	dft(comImg, comImg);

	split(comImg, planes);
	magnitude(planes[0], planes[1], planes[0]);

	Mat magMat = planes[0];
	magMat += Scalar::all(1);
	log(magMat, magMat);

	magMat = magMat(Rect(0, 0, magMat.cols & -2, magMat.rows & -2));

	int cx = magMat.cols / 2;
	int cy = magMat.rows / 2;

	Mat q0(magMat, Rect(0, 0, cx, cy));
	Mat q1(magMat, Rect(0, cy, cx, cy));
	Mat q2(magMat, Rect(cx, cy, cx, cy));
	Mat q3(magMat, Rect(cx, 0, cx, cy));

	Mat tmp;
	q0.copyTo(tmp);
	q2.copyTo(q0);
	tmp.copyTo(q2);

	q1.copyTo(tmp);
	q3.copyTo(q1);
	tmp.copyTo(q3);

	normalize(magMat, magMat, 0, 1, CV_MINMAX);
	Mat magImg(magMat.size(), CV_8UC1);
	magMat.convertTo(magImg, CV_8UC1, 255, 0);

	threshold(magImg, magImg, GRAY_THRESH, 255, CV_THRESH_BINARY);

	vector<Vec2f> lines;
	float pi180 = (float)CV_PI / 180;
	Mat linImg(magImg.size(), CV_8UC3);
	HoughLines(magImg, lines, 1, pi180, HOUGH_VOTE, 0, 0);
	int numLines = lines.size();
	for (int l = 0; l < numLines; l++)
	{
		float rho = lines[l][0], theta = lines[l][1];
		Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a * rho, y0 = b * rho;
		pt1.x = cvRound(x0 + 1000 * (-b));
		pt1.y = cvRound(y0 + 1000 * (a));
		pt2.x = cvRound(x0 - 1000 * (-b));
		pt2.y = cvRound(y0 - 1000 * (a));
		line(linImg, pt1, pt2, Scalar(255, 0, 0), 3, 8, 0);
	}


	if (lines.size() == 3) {
		cout << "found three angels:" << endl;
		cout << lines[0][1] * 180 / CV_PI << endl << lines[1][1] * 180 / CV_PI << endl << lines[2][1] * 180 / CV_PI << endl << endl;
	}


	float angel = 0;
	float piThresh = (float)CV_PI / 90;
	float pi2 = CV_PI / 2;
	for (int l = 0; l < numLines; l++)
	{
		float theta = lines[l][1];
		if (abs(theta) < piThresh || abs(theta - pi2) < piThresh)
			continue;
		else {
			angel = theta;
			break;
		}
	}


	angel = angel < pi2 ? angel : angel - CV_PI;
	if (angel != pi2) {
		float angelT = srcImg.rows*tan(angel) / srcImg.cols;
		angel = atan(angelT);
	}
	float angelD = angel * 180 / (float)CV_PI;
	cout << "the rotation angel to be applied:" << endl << angelD << endl << endl;


	Mat rotMat = getRotationMatrix2D(center, angelD, 1.0);
	Mat dstImg = Mat::ones(srcImg.size(), CV_8UC3);
	warpAffine(srcImg, dstImg, rotMat, srcImg.size(), 1, 0, Scalar(255, 255, 255));
	return dstImg;
}

void CMyNew::OnBnClickedButton14()
{
	Mat dstImg = imgCorrect(image);
	Mat imagedst;
	CRect rect;
	GetDlgItem(IDC_PIC_STATIC1)->GetClientRect(&rect);
	Rect dst(rect.left, rect.top, rect.right, rect.bottom);
	resize(dstImg, imagedst, cv::Size(rect.Width(), rect.Height()));
	imshow("view1", imagedst);  //显示当前帧

}
